Optimize queue_resize_on_widget()
authorTristan Van Berkom <tristan.van.berkom@gmail.com>
Mon, 7 Feb 2011 07:55:25 +0000 (16:55 +0900)
committerTristan Van Berkom <tristan.van.berkom@gmail.com>
Mon, 7 Feb 2011 15:39:51 +0000 (00:39 +0900)
Optimized GtkSizeGroup code that is invoked for every queued resize
and every request that is not previously cached by trading qdata on
widgets for 3 extra bitfields on the GtkWidgetPrivate structure.

gtk/gtksizegroup.c
gtk/gtkwidget.c
gtk/gtkwidgetprivate.h

index 54042a0ed7a2e3f9fa4efea48b745076b3bec2d1..5a686a2d4ee3274307c67dc1b5ce287a5a3193d9 100644 (file)
@@ -41,6 +41,7 @@ struct _GtkSizeGroupPrivate
   guint           have_width    : 1;
   guint           have_height   : 1;
   guint           ignore_hidden : 1;
+  guint           visited       : 1;
 };
 
 enum {
@@ -81,56 +82,16 @@ static void gtk_size_group_buildable_custom_finished (GtkBuildable  *buildable,
                                                      const gchar   *tagname,
                                                      gpointer       user_data);
 
-static GQuark size_groups_quark;
-static const gchar size_groups_tag[] = "gtk-size-groups";
-
-static GQuark visited_quark;
-static const gchar visited_tag[] = "gtk-size-group-visited";
-
-static GQuark bumping_quark;
-static const gchar bumping_tag[] = "gtk-size-group-bumping";
-
-static GSList *
-get_size_groups (GtkWidget *widget)
-{
-  return g_object_get_qdata (G_OBJECT (widget), size_groups_quark);
-}
-
 static void
-set_size_groups (GtkWidget *widget,
-                GSList    *groups)
-{
-  g_object_set_qdata (G_OBJECT (widget), size_groups_quark, groups);
-}
-
-static void
-mark_visited (gpointer object)
-{
-  g_object_set_qdata (object, visited_quark, "visited");
-}
-
-static void
-mark_unvisited (gpointer object)
-{
-  g_object_set_qdata (object, visited_quark, NULL);
-}
-
-static gboolean
-is_visited (gpointer object)
+mark_group_unvisited (GtkSizeGroup *group)
 {
-  return g_object_get_qdata (object, visited_quark) != NULL;
+  group->priv->visited = FALSE;
 }
 
 static void
-mark_bumping (gpointer object, gboolean bumping)
-{
-  g_object_set_qdata (object, bumping_quark, bumping ? "bumping" : NULL);
-}
-
-static gboolean
-is_bumping (gpointer object)
+mark_widget_unvisited (GtkWidget *widget)
 {
-  return g_object_get_qdata (object, bumping_quark) != NULL;
+  _gtk_widget_set_sizegroup_visited (widget, FALSE);
 }
 
 static void
@@ -143,14 +104,14 @@ add_group_to_closure (GtkSizeGroup    *group,
   GSList *tmp_widgets;
   
   *groups = g_slist_prepend (*groups, group);
-  mark_visited (group);
+  priv->visited = TRUE;
 
   tmp_widgets = priv->widgets;
   while (tmp_widgets)
     {
       GtkWidget *tmp_widget = tmp_widgets->data;
       
-      if (!is_visited (tmp_widget))
+      if (!_gtk_widget_get_sizegroup_visited (tmp_widget))
        add_widget_to_closure (tmp_widget, mode, groups, widgets);
       
       tmp_widgets = tmp_widgets->next;
@@ -166,16 +127,16 @@ add_widget_to_closure (GtkWidget       *widget,
   GSList *tmp_groups;
 
   *widgets = g_slist_prepend (*widgets, widget);
-  mark_visited (widget);
+  _gtk_widget_set_sizegroup_visited (widget, TRUE);
 
-  tmp_groups = get_size_groups (widget);
+  tmp_groups = _gtk_widget_get_sizegroups (widget);
   while (tmp_groups)
     {
-      GtkSizeGroup *tmp_group = tmp_groups->data;
-      GtkSizeGroupPrivate *tmp_priv = tmp_group->priv;
+      GtkSizeGroup        *tmp_group = tmp_groups->data;
+      GtkSizeGroupPrivate *tmp_priv  = tmp_group->priv;
 
       if ((tmp_priv->mode == GTK_SIZE_GROUP_BOTH || tmp_priv->mode == mode) &&
-         !is_visited (tmp_group))
+         !tmp_group->priv->visited)
        add_group_to_closure (tmp_group, mode, groups, widgets);
 
       tmp_groups = tmp_groups->next;
@@ -243,7 +204,7 @@ queue_resize_on_widget (GtkWidget          *widget,
          continue;
        }
       
-      widget_groups = get_size_groups (parent);
+      widget_groups = _gtk_widget_get_sizegroups (parent);
       if (!widget_groups)
        {
          if (widget == parent)
@@ -257,8 +218,8 @@ queue_resize_on_widget (GtkWidget          *widget,
       widgets = NULL;
          
       add_widget_to_closure (parent, GTK_SIZE_GROUP_HORIZONTAL, &groups, &widgets);
-      g_slist_foreach (widgets, (GFunc)mark_unvisited, NULL);
-      g_slist_foreach (groups, (GFunc)mark_unvisited, NULL);
+      g_slist_foreach (widgets, (GFunc)mark_widget_unvisited, NULL);
+      g_slist_foreach (groups, (GFunc)mark_group_unvisited, NULL);
 
       reset_group_sizes (groups);
              
@@ -287,8 +248,8 @@ queue_resize_on_widget (GtkWidget          *widget,
       widgets = NULL;
              
       add_widget_to_closure (parent, GTK_SIZE_GROUP_VERTICAL, &groups, &widgets);
-      g_slist_foreach (widgets, (GFunc)mark_unvisited, NULL);
-      g_slist_foreach (groups, (GFunc)mark_unvisited, NULL);
+      g_slist_foreach (widgets, (GFunc)mark_widget_unvisited, NULL);
+      g_slist_foreach (groups, (GFunc)mark_group_unvisited, NULL);
 
       reset_group_sizes (groups);
              
@@ -326,17 +287,6 @@ queue_resize_on_group (GtkSizeGroup       *size_group)
     queue_resize_on_widget (priv->widgets->data, TRUE, 0);
 }
 
-static void
-initialize_size_group_quarks (void)
-{
-  if (!size_groups_quark)
-    {
-      size_groups_quark = g_quark_from_static_string (size_groups_tag);
-      visited_quark = g_quark_from_static_string (visited_tag);
-      bumping_quark = g_quark_from_static_string (bumping_tag);
-    }
-}
-
 static void
 gtk_size_group_class_init (GtkSizeGroupClass *klass)
 {
@@ -372,8 +322,6 @@ gtk_size_group_class_init (GtkSizeGroupClass *klass)
                                                         GTK_PARAM_READWRITE));
 
   g_type_class_add_private (klass, sizeof (GtkSizeGroupPrivate));
-
-  initialize_size_group_quarks ();
 }
 
 static void
@@ -391,6 +339,7 @@ gtk_size_group_init (GtkSizeGroup *size_group)
   priv->have_width = 0;
   priv->have_height = 0;
   priv->ignore_hidden = 0;
+  priv->visited  = FALSE;
 }
 
 static void
@@ -600,12 +549,11 @@ gtk_size_group_add_widget (GtkSizeGroup     *size_group,
 
   priv = size_group->priv;
 
-  groups = get_size_groups (widget);
+  groups = _gtk_widget_get_sizegroups (widget);
 
   if (!g_slist_find (groups, size_group))
     {
-      groups = g_slist_prepend (groups, size_group);
-      set_size_groups (widget, groups);
+      _gtk_widget_add_sizegroup (widget, size_group);
 
       priv->widgets = g_slist_prepend (priv->widgets, widget);
 
@@ -631,7 +579,6 @@ gtk_size_group_remove_widget (GtkSizeGroup *size_group,
                              GtkWidget    *widget)
 {
   GtkSizeGroupPrivate *priv;
-  GSList *groups;
   
   g_return_if_fail (GTK_IS_SIZE_GROUP (size_group));
   g_return_if_fail (GTK_IS_WIDGET (widget));
@@ -644,9 +591,7 @@ gtk_size_group_remove_widget (GtkSizeGroup *size_group,
                                        gtk_size_group_widget_destroyed,
                                        size_group);
   
-  groups = get_size_groups (widget);
-  groups = g_slist_remove (groups, size_group);
-  set_size_groups (widget, groups);
+  _gtk_widget_remove_sizegroup (widget, size_group);
 
   priv->widgets = g_slist_remove (priv->widgets, widget);
   queue_resize_on_group (size_group);
@@ -684,10 +629,9 @@ compute_dimension (GtkWidget        *widget,
   gint    min_result = 0, nat_result = 0;
 
   add_widget_to_closure (widget, mode, &groups, &widgets);
+  g_slist_foreach (widgets, (GFunc)mark_widget_unvisited, NULL);
+  g_slist_foreach (groups, (GFunc)mark_group_unvisited, NULL);
 
-  g_slist_foreach (widgets, (GFunc)mark_unvisited, NULL);
-  g_slist_foreach (groups, (GFunc)mark_unvisited, NULL);
-  
   g_slist_foreach (widgets, (GFunc)g_object_ref, NULL);
   
   if (!groups)
@@ -755,7 +699,6 @@ compute_dimension (GtkWidget        *widget,
              else
                {
                  tmp_priv->have_height = TRUE;
-
                  tmp_priv->minimum_req.height = min_result;
                  tmp_priv->natural_req.height = nat_result;
                }
@@ -795,15 +738,15 @@ _gtk_size_group_bump_requisition (GtkWidget        *widget,
                                  gint             *minimum,
                                  gint             *natural)
 {
-  if (!is_bumping (widget))
+  if (!_gtk_widget_get_sizegroup_bumping (widget))
     {
       /* Avoid recursion here */
-      mark_bumping (widget, TRUE);
+      _gtk_widget_set_sizegroup_bumping (widget, TRUE);
 
-      if (get_size_groups (widget))
+      if (_gtk_widget_get_sizegroups (widget))
        compute_dimension (widget, mode, minimum, natural);
 
-      mark_bumping (widget, FALSE);
+      _gtk_widget_set_sizegroup_bumping (widget, FALSE);
     }
 }
 
@@ -819,8 +762,6 @@ void
 _gtk_size_group_queue_resize (GtkWidget           *widget,
                              GtkQueueResizeFlags  flags)
 {
-  initialize_size_group_quarks ();
-
   queue_resize_on_widget (widget, TRUE, flags);
 }
 
index bea97d816bac3e50dba6ae6c2d6fee99c009ed26..410f493fcae56fdc4fb5bdbebdb6ec0c5863e61f 100644 (file)
@@ -324,6 +324,8 @@ struct _GtkWidgetPrivate
   guint multidevice           : 1;
   guint has_shape_mask        : 1;
   guint in_reparent           : 1;
+
+  /* Queue-resize related flags */
   guint resize_pending        : 1;
   guint alloc_needed          : 1;
   guint width_request_needed  : 1;
@@ -338,6 +340,11 @@ struct _GtkWidgetPrivate
   guint hexpand_set           : 1; /* whether to use application-forced  */
   guint vexpand_set           : 1; /* instead of computing from children */
 
+  /* SizeGroup related flags */
+  guint sizegroup_visited     : 1;
+  guint sizegroup_bumping     : 1;
+  guint have_size_groups      : 1;
+
   /* The widget's name. If the widget does not have a name
    *  (the name is NULL), then its name (as returned by
    *  "gtk_widget_get_name") is its class's name.
@@ -697,6 +704,7 @@ static GQuark               quark_tooltip_window = 0;
 static GQuark          quark_visual = 0;
 static GQuark           quark_modifier_style = 0;
 static GQuark           quark_enabled_devices = 0;
+static GQuark           quark_size_groups = 0;
 GParamSpecPool         *_gtk_widget_child_property_pool = NULL;
 GObjectNotifyContext   *_gtk_widget_child_property_notify_context = NULL;
 
@@ -811,6 +819,7 @@ gtk_widget_class_init (GtkWidgetClass *klass)
   quark_visual = g_quark_from_static_string ("gtk-widget-visual");
   quark_modifier_style = g_quark_from_static_string ("gtk-widget-modifier-style");
   quark_enabled_devices = g_quark_from_static_string ("gtk-widget-enabled-devices");
+  quark_size_groups = g_quark_from_static_string ("gtk-widget-size-groups");
 
   style_property_spec_pool = g_param_spec_pool_new (FALSE);
   _gtk_widget_child_property_pool = g_param_spec_pool_new (TRUE);
@@ -14064,6 +14073,67 @@ _gtk_widget_set_height_request_needed (GtkWidget *widget,
   widget->priv->height_request_needed = height_request_needed;
 }
 
+gboolean
+_gtk_widget_get_sizegroup_visited (GtkWidget    *widget)
+{
+  return widget->priv->sizegroup_visited;
+}
+
+void
+_gtk_widget_set_sizegroup_visited (GtkWidget    *widget,
+                                  gboolean      visited)
+{
+  widget->priv->sizegroup_visited = visited;
+}
+
+gboolean
+_gtk_widget_get_sizegroup_bumping (GtkWidget    *widget)
+{
+  return widget->priv->sizegroup_bumping;
+}
+
+void
+_gtk_widget_set_sizegroup_bumping (GtkWidget    *widget,
+                                  gboolean      bumping)
+{
+  widget->priv->sizegroup_bumping = bumping;
+}
+
+void
+_gtk_widget_add_sizegroup (GtkWidget    *widget,
+                          gpointer      group)
+{
+  GSList *groups;
+
+  groups = g_object_get_qdata (G_OBJECT (widget), quark_size_groups);
+  groups = g_slist_prepend (groups, group);
+  g_object_set_qdata (G_OBJECT (widget), quark_size_groups, groups);
+
+  widget->priv->have_size_groups = TRUE;
+}
+
+void
+_gtk_widget_remove_sizegroup (GtkWidget    *widget,
+                             gpointer      group)
+{
+  GSList *groups;
+
+  groups = g_object_get_qdata (G_OBJECT (widget), quark_size_groups);
+  groups = g_slist_remove (groups, group);
+  g_object_set_qdata (G_OBJECT (widget), quark_size_groups, groups);
+
+  widget->priv->have_size_groups = groups != NULL;
+}
+
+GSList *
+_gtk_widget_get_sizegroups (GtkWidget    *widget)
+{
+  if (widget->priv->have_size_groups)
+    return g_object_get_qdata (G_OBJECT (widget), quark_size_groups);
+
+  return NULL;
+}
+
 /**
  * gtk_widget_get_path:
  * @widget: a #GtkWidget
index 778fff2b3552dbcc9df49a9e93e1d2e80e31c986..1e91290d051718b68cc89bc983067701ca1a9edb 100644 (file)
@@ -79,6 +79,18 @@ gboolean     _gtk_widget_get_height_request_needed (GtkWidget *widget);
 void         _gtk_widget_set_height_request_needed (GtkWidget *widget,
                                                     gboolean   height_request_needed);
 
+gboolean     _gtk_widget_get_sizegroup_visited (GtkWidget    *widget);
+void         _gtk_widget_set_sizegroup_visited (GtkWidget    *widget,
+                                               gboolean      visited);
+gboolean     _gtk_widget_get_sizegroup_bumping (GtkWidget    *widget);
+void         _gtk_widget_set_sizegroup_bumping (GtkWidget    *widget,
+                                               gboolean      bumping);
+void         _gtk_widget_add_sizegroup         (GtkWidget    *widget,
+                                               gpointer      group);
+void         _gtk_widget_remove_sizegroup      (GtkWidget    *widget,
+                                               gpointer      group);
+GSList      *_gtk_widget_get_sizegroups        (GtkWidget    *widget);
+
 void _gtk_widget_override_size_request (GtkWidget *widget,
                                         int        width,
                                         int        height,